home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / RandomDot 1.1.0 / source / RandomDotWin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-07  |  16.4 KB  |  621 lines  |  [TEXT/KAHL]

  1. /* RandomDotWin.c
  2.     by David Phillip Oster October 1994 oster@netcom.com
  3.     for:
  4.     Stuart Inglis singlis@waikato.ac.nz
  5.     Department of Computer Science
  6.     University of Waikato, Hamilton, New Zealand
  7.  */
  8. #include <PictUtil.h>
  9. #include "RandomDotMain.h"
  10. #include "RandomDotRes.h"
  11.  
  12. #include "RandomDotWin.h"
  13. #include "RandomDotWinCommands.h"
  14.  
  15. #include "Error.h"
  16. #include "Menu.h"
  17. #include "pgm.h"
  18. #include "RandomDot.h"
  19. #include "Utils.h"
  20. #include "RandomDotScroll.h"
  21.  
  22. #define round(X)    ((int) ((X) + 0.5))
  23.  
  24.  
  25.  
  26. /* private prototypes
  27.  */
  28. static void CopyPicToGWorld(void);
  29. //static void RandomDotPalette(void);
  30.  
  31. static void NoWindowActivateMenus(void);
  32. static void RandomDotActivateMenus(void);
  33.  
  34.  
  35. CTabHandle        grayCTab = NIL;
  36. static CTabHandle    shimmerCT;
  37. static PaletteHandle grayPalette = NIL;
  38. static PaletteHandle shimmerPalette = NIL;
  39.  
  40.  
  41. /* SetCTGrayRamp - set a Color Table, assumed to be 256 long, to uniform grays,
  42.     where the indices match the complement of the gray value.
  43.  
  44.     Note: there is a bug in System 7.1 with the LaserWriter driver such that if
  45.         you CopyBits() to the printer, with an 8-bit indexed offscreen gworld
  46.         as the source, the first and last entries of the color table of the
  47.         offscreen gworld get set so the first is white and the last is black.
  48.         So, we follow that scheme in this program: for an 8-bit pixmap index,
  49.         the gray scale value is the complement of the index.
  50.         Watch out, expressions evaluate to ints in C, so ~(unsigned char) 1
  51.         if 0xFFFE not 0xFE
  52.  */
  53. static void SetCTGrayRamp(CTabHandle ct, Integer start, Integer stop){
  54.     LongInt        seed;
  55.     Integer        i;
  56.     unsigned short j;
  57.     ColorSpec    *sp;
  58.  
  59.     seed = GetCTSeed();
  60.     (**ct).ctSeed = seed;
  61.     sp = (**ct).ctTable;
  62.     for(i = start ; i <= stop ; i++, sp++){
  63.         j = ~i & 0xFF;
  64.         sp->rgb.red = sp->rgb.green = sp->rgb.blue = j << 8 | j;
  65.         sp->value = i;
  66.     }
  67. }
  68.  
  69.  
  70. /* InitRandomDot - one time initializations. 
  71.     create a colortable that maps 0..255 into the matching shades of gray.
  72.     The palette manager wants to autmatically add white and black, so we
  73.     create a CTabHandle for palettes that is the same as grayCTab, but excludes
  74.     white and black.
  75.  */
  76. OSErr InitRandomDot(void){
  77.     LongInt        seed;
  78.     OSErr        errCode;
  79.     CTabHandle paletteCTab;
  80.  
  81.     grayCTab = (CTabHandle) NewHandle(sizeof(long) + sizeof(short) + sizeof(short) + 256L*sizeof(ColorSpec));
  82.     if(noErr == (errCode = MemError())){
  83.         (**grayCTab).ctFlags = 0;
  84.         (**grayCTab).ctSize = 255;
  85.         SetCTGrayRamp(grayCTab, 0, 255);
  86.     }
  87.     if(noErr == errCode){
  88.         paletteCTab = (CTabHandle) NewHandle(sizeof(long) + sizeof(short) + sizeof(short) + 254L*sizeof(ColorSpec));
  89.         if(noErr == (errCode = MemError())){
  90.             (**paletteCTab).ctFlags = 0;
  91.             (**paletteCTab).ctSize = 253;
  92.             SetCTGrayRamp(paletteCTab, 1, 254);
  93.             grayPalette = NewPalette(254, paletteCTab, pmTolerant, 0);
  94.             shimmerPalette = NewPalette(254, paletteCTab, pmAnimated, 0);
  95.             DisposeHandle((Handle) paletteCTab);
  96.             shimmerCT = grayCTab;
  97.             if(noErr == (errCode = HandToHand((Handle *) &shimmerCT))){
  98.                 seed = GetCTSeed();
  99.                 (**shimmerCT).ctSeed = seed;
  100.                 (**shimmerCT).ctFlags |= 0x4000;    /* palette animation */
  101.             }else{
  102.                 shimmerCT = NIL;
  103.             }
  104.         }
  105.     }
  106.     return errCode;
  107. }
  108.  
  109.  
  110. /* PICTFileToGWorld - read a pict into a gray scale gworld
  111.  */
  112. static OSErr PICTFileToGWorld(FSSpecPtr fs, ScriptCode code, GWorldPtr *gworld){
  113.     OSErr                errCode;
  114.     PicHandle            ph;
  115.     PictInfo            pInfo;
  116.     Integer                ref;
  117.     LongInt                len;
  118.     Rect                frame;
  119.     CGrafPtr            savePort;
  120.     GDHandle            saveGD;
  121.     GWorldPtr            grayImage;
  122.     PixMapHandle        pm;
  123.  
  124.     errCode = noErr;
  125.     ph = NIL;
  126.     if(noErr == errCode){ errCode = FSpOpenDF(fs, fsCurPerm, &ref); }
  127.     if(noErr == errCode){ errCode = GetEOF(ref, &len);}
  128.     if(noErr == errCode && len < 512){ errCode = eBadPict; }
  129.     if(noErr == errCode){ len -= 512; errCode = SetFPos(ref, fsFromStart, 512L); }
  130.     if(noErr == errCode){ ph = (PicHandle) NewHandle(len); errCode = MemError(); }
  131.     if(noErr == errCode){
  132.         HLock((Handle) ph);
  133.         errCode = FSRead(ref, &len, *ph);
  134.         HUnlock((Handle) ph);
  135.     }
  136.     if(-1 != ref){ FSClose(ref); }
  137.     if(noErr != errCode){
  138.         if(NIL != ph){
  139.             KillPicture(ph);
  140.         }
  141.         return errCode;
  142.     }
  143.     frame = (**ph).picFrame;
  144. /* if the picture isn't 72 dpi, we'll need to scale the frame.
  145.  */
  146.      GetPictInfo(ph, &pInfo, 0, 0, systemMethod, 0);
  147.     OffsetRect(&frame, -frame.left, -frame.top);    /* 0 base the frame */
  148.     if(pInfo.hRes != (72L <<16) || pInfo.vRes != (72L <<16)){
  149.         frame.right = round( frame.right*(pInfo.hRes/(65536.*72.)));
  150.         frame.bottom = round( frame.bottom*(pInfo.hRes/(65536.*72.)));
  151.     }
  152.  
  153.     GetGWorld(&savePort, &saveGD);
  154.     if(noErr == (errCode = NewGWorld(&grayImage, 8, &frame, grayCTab, NIL, 0)) &&
  155.         NIL != grayImage){
  156.  
  157.         SetGWorld(grayImage, NIL);
  158.         ClipRect(&qd.thePort->portRect);
  159.         pm = GetGWorldPixMap(grayImage);
  160.         LockPixels(pm);
  161.         DrawPicture(ph, &frame);
  162.         UnlockPixels(pm);
  163.         KillPicture(ph);
  164.         ph = NIL;
  165.         *gworld = grayImage;
  166.     }
  167.     SetGWorld(savePort, saveGD);
  168.     
  169.     return errCode;
  170. }
  171.  
  172. /* FileToGWorld - switch based on the file type
  173.  */
  174. static OSErr FileToGWorld(OSType type, FSSpecPtr fs, ScriptCode code, GWorldPtr *gworld){
  175.     switch(type){
  176.     case 'PICT':    return PICTFileToGWorld(fs, code, gworld);
  177.     default:        return PGMFileToGWorld(fs, code, gworld);
  178.     }
  179.     return eBadFileType;
  180. }
  181.  
  182. /* InitialGray - return TRUE if window intersects a device capable of
  183.     displaying gray.
  184.  */
  185. static Boolean InitialGray(void){
  186.     Rect    r;
  187.  
  188.     r = qd.thePort->portRect;
  189.     LocalToGlobal(&topLeft(r));
  190.     LocalToGlobal(&botRight(r));
  191.     return world.hasColorQD && (**(**GetMaxDevice(&r)).gdPMap).pixelSize > 1;
  192. }
  193.  
  194. /* RandomDotOpenFile - 
  195.     make a new window, 
  196.     read a PICT or pgm file in its entirety in to a handle and attach it.
  197.  */
  198. static OSErr RandomDotOpenFile(FSSpecPtr fs, ScriptCode code){
  199.     OSErr                errCode;
  200.     FInfo    fInfo;
  201.     Integer                ref;
  202.     RandomDotWindowPtr    win;
  203.     CGrafPtr            savePort;
  204.     GDHandle            saveGD;
  205.     Boolean                initialGray;
  206.  
  207.     if(noErr != (errCode = FSpGetFInfo(fs, &fInfo))){
  208.         return errCode;
  209.     }
  210.     if(kPrefType == fInfo.fdType){
  211.         return noErr;
  212.     }
  213.     ref = -1;
  214.     win = (RandomDotWindowPtr) NewPtrClear(sizeof(RandomDotWindowRec));
  215.     if(world.hasColorQD){
  216.         SetPort(GetNewCWindow(rWin, (Ptr) win, (WindowPtr) -1L));
  217.     }else{
  218.         SetPort(GetNewWindow(rWin, (Ptr) win, (WindowPtr) -1L));
  219.     }
  220.     win->hScroll = GetNewControl(128, qd.thePort);
  221.     InitScrollBarClass(&HProcs);
  222.     SetCRefCon(win->hScroll, (LongInt) &HProcs);
  223.     win->vScroll = GetNewControl(128, qd.thePort);
  224.     InitScrollBarClass(&VProcs);
  225.     SetCRefCon(win->vScroll, (LongInt) &VProcs);
  226.     win->fs = *fs;
  227.     win->code = code;
  228.     SetWTitle(qd.thePort, fs->name);
  229.     errCode = MemError();
  230.     GetGWorld(&savePort, &saveGD);
  231.     initialGray = InitialGray();
  232.     if(noErr == errCode){ errCode = FileToGWorld(fInfo.fdType, fs, code, &win->grayImage); }
  233.     if(noErr == errCode){ errCode = NewGWorld(&win->stereoImage, 8, &win->grayImage->portRect, grayCTab, NIL, 0); }
  234.     if(noErr == errCode){
  235.         SetGWorld(win->stereoImage, NIL);
  236.         ClipRect(&qd.thePort->portRect);
  237.         SetGWorld(savePort, saveGD);
  238.         win->flags |= initialGray ? (bIsGray|bShowGrayStereo) : bShowBWStereo;
  239.     }
  240.     if(noErr == errCode){ errCode = ComputeAutoStereogram(win->grayImage, win->stereoImage, 0 != (bIsGray & win->flags)); }
  241.     if(noErr == errCode && FreeMem() < 50000L){ errCode = memFullErr; }
  242.     SetGWorld(savePort, saveGD);
  243.     if(noErr != errCode){
  244.         if(NIL != win){
  245.             RandomDotDisposeWindow((WindowPtr) win);
  246.         }
  247.     }else{
  248.         win->frame = win->grayImage->portRect;
  249.         if(world.hasColorQD){
  250.             RandomDotPalette();
  251.         }
  252.         ZoomWindow((WindowPtr) win, inZoomOut, FALSE);
  253.         RandomDotGrow();
  254.         ShowWindow((WindowPtr) win);
  255.         SelectWindow((WindowPtr) win);
  256.     }
  257.     return errCode;
  258. }
  259.  
  260.  
  261.  
  262. /* RandomDotPalette - set the palette for this window to a gray ramp.
  263.     Inside Mac says it is ok for windows to share a palette
  264.  */
  265. void RandomDotPalette(void){
  266.     NSetPalette(qd.thePort,  grayPalette, pmFgUpdates);
  267. }
  268.  
  269. /* ShimmerDotPalette - set the palette for this window to an animating
  270.     palette.
  271.  */
  272. void ShimmerDotPalette(void){
  273.     NSetPalette(qd.thePort,  shimmerPalette, pmFgUpdates);
  274. }
  275.  
  276.  
  277. /* RandomDotOpenWindow - if fs equals an existing window, return it.
  278.  */
  279. static WindowPtr RandomDotOpenWindow(FSSpecPtr fs, ScriptCode code){
  280.     WindowPtr    win;
  281.  
  282.     for(win = FrontWindow(); NIL != win; win = (WindowPtr) ((WindowPeek) win)->nextWindow){
  283.         if(((WindowPeek) win)->visible && 
  284.             userKind == ((WindowPeek) win)->windowKind &&
  285.             EqualFSSpec(fs, &((RandomDotWindowPtr) win)->fs) &&
  286.             code == ((RandomDotWindowPtr) win)->code){
  287.  
  288.             return win;
  289.         }
  290.     }
  291.     return NIL;
  292. }
  293.  
  294.  
  295. /* RandomDotOpen - make a new window, and attach the pict to it.
  296.  */
  297. OSErr RandomDotOpen(FSSpecPtr fs, ScriptCode code){
  298.     WindowPtr    win;
  299.  
  300.     if(NIL != (win = RandomDotOpenWindow(fs, code))){
  301.         SelectWindow(win);
  302.         return noErr;
  303.     }else{
  304.         return RandomDotOpenFile(fs, code);
  305.     }
  306. }
  307.  
  308. /* RandomDotDisposeWindow - we are done with the window. dump the
  309.     data structures.
  310.  
  311.  */
  312. void RandomDotDisposeWindow(WindowPtr xin){
  313.     RandomDotWindowPtr    win;
  314.  
  315.     win = (RandomDotWindowPtr) xin;
  316.     if(NIL != win->grayImage){
  317.         DisposeGWorld(win->grayImage);
  318.     }
  319.     if(NIL != win->stereoImage){
  320.         DisposeGWorld(win->stereoImage);
  321.     }
  322.     DisposeWindow(xin);
  323.     if(NIL == FrontWindow()){
  324.         NoWindowActivateMenus();
  325.     }
  326. }
  327.  
  328. /* RandomDotKey - handle key down in the window.
  329.  */
  330. void RandomDotKey(EventRecord *e){
  331. }
  332.  
  333. /* RandomDotClick - handle mouse down in the window
  334.  */
  335. void RandomDotClick(EventRecord *e){
  336.     Rect    contents;
  337.     Point    where;
  338.  
  339.     if(qd.thePort != FrontWindow()){
  340.         SelectWindow(qd.thePort);
  341.         return;
  342.     }
  343.     where = e->where;
  344.     GlobalToLocal(&where);
  345.     GetContentsRect(&contents);
  346.     if(NOT TrackScroll(where)){
  347.         /* empty */
  348.     }
  349. }
  350.  
  351. /* Roll - return a number from lo to hi, inclusive
  352.  */
  353. static Integer Roll(Integer lo, Integer hi){
  354.     return lo + ((unsigned) Random()) % ( hi - lo);
  355. }
  356.  
  357. /* ShuffleCTab - shuffle the entries in a CTabHandle from lo to high
  358.     inclusive.
  359.  */
  360. static void ShuffleCTab(CTabHandle ct, Integer lo, Integer hi){
  361.     Integer i, j;
  362.     ColorSpec    t;
  363.  
  364.     for( i = hi ; i > lo+1 ; i--){
  365.         j = Roll(lo, i);
  366.         t = (**ct).ctTable[j];
  367.         (**ct).ctTable[j] = (**ct).ctTable[i];
  368.         (**ct).ctTable[i] = t;
  369.     }
  370. }
  371.  
  372.  
  373. /* RandomDotIdle - 
  374.  */
  375. void RandomDotIdle(EventRecord *e){
  376.     static unsigned long last;
  377.     RandomDotWindowPtr    win;
  378.     
  379.     if(e->when == last || e->when == last + 1){
  380.         return;
  381.     }
  382.     last = e->when;
  383.     win = (RandomDotWindowPtr) qd.thePort;
  384.     if((bIsShimmer & win->flags) && NIL != shimmerCT){
  385.         ShuffleCTab(shimmerCT, 1, 254);
  386.         AnimatePalette(qd.thePort, shimmerCT, 0, 0, 256);
  387.     }
  388. }
  389.  
  390.  
  391. /* RandomDotGWorld - return the GWorld to draw.
  392.  */
  393. static GWorldPtr RandomDotGWorld(RandomDotWindowPtr win){
  394.     switch(win->flags & (bShowGray|bShowBWStereo|bShowGrayStereo)){
  395.     case bShowGray:            return win->grayImage;    break;
  396.     case bShowBWStereo:    
  397.     case bShowGrayStereo:    return win->stereoImage;    break;
  398.     }
  399.     return NIL;
  400. }
  401.  
  402. /* RandomDotCopybitsWin - used for Update, Print and in Save and Copy
  403.     draws the image using the framep rect on the current grafport.
  404.  */
  405. void RandomDotCopybitsWin(RandomDotWindowPtr win, Rect *framep){
  406.     PixMapHandle        pm;
  407.     GWorldPtr            gworld;
  408.  
  409.     if(NIL != (gworld = RandomDotGWorld(win))){
  410.         pm = GetGWorldPixMap(gworld);
  411.         LockPixels(pm);
  412.         CopyBits((BitMap *) *pm, &qd.thePort->portBits, &win->frame, framep, srcCopy, NIL);
  413.         UnlockPixels(pm);
  414.     }
  415. }
  416.  
  417.  
  418.  
  419. /* RandomDotUpdate - handle redrawing the window
  420.     partial updates in shimmer mode weren't working right, so we swap the
  421.     palette back. but if whole thing is being updated, then we don't
  422.     swap the palette to avoid excessive screen flicker.
  423.  
  424.     Note 1: In order to write to a window using an animated palette,
  425.         we need to set bit 14 of the color table flags, so that CopyBits
  426.         will use the color table indices to map values.
  427.  */
  428. void RandomDotUpdate(void){
  429.     RandomDotWindowPtr    win;
  430.     Rect                frame;
  431.     Rect                contents;
  432.     RgnHandle            saveRgn;
  433.     PixMapHandle        pm;
  434.     GWorldPtr            gworld;
  435.     CTabHandle            ct;
  436.  
  437.     win = (RandomDotWindowPtr) qd.thePort;
  438.     if(userKind == ((WindowPeek) win)->windowKind){
  439.         ct = NIL;
  440.         DrawControls(qd.thePort);
  441.         DrawGrowIcon(qd.thePort);
  442.         frame = win->frame;
  443.         OffsetRect(&frame, 
  444.             -GetControlValue(win->hScroll)-frame.left, 
  445.             -GetControlValue(win->vScroll)-frame.top);
  446.         GetContentsRect(&contents);
  447.         if((bIsShimmer|bShowGrayStereo) == (kShow & win->flags) &&
  448.             NIL != (gworld = RandomDotGWorld(win)) &&
  449.             NIL != (pm = GetGWorldPixMap(gworld)) &&
  450.             NIL != (ct = (**pm).pmTable)){
  451.  
  452.             (**ct).ctFlags |= 0x4000;    /* Note 1 */
  453.         }
  454.         saveRgn = RestrictClipRect(&contents);
  455.         RandomDotCopybitsWin(win, &frame);
  456.         RestoreClip(saveRgn);
  457.         if(NIL != ct){
  458.             (**ct).ctFlags &= ~0x4000;    /* Note 1 */
  459.         }
  460.     }
  461. }
  462.  
  463. /* NoWindowActivateMenus - 
  464.  */
  465. static void NoWindowActivateMenus(void){
  466.     MenuHandle    mh;
  467.  
  468.     mh = GetMHandle(kFileMenu);
  469.     DisableItem(mh, kCloseI);
  470.     DisableItem(mh, kSaveI);
  471.     DisableItem(mh, kSaveAsI);
  472.     DisableItem(mh, kPrintI);
  473.     mh = GetMHandle(kEditMenu);
  474.     DisableItem(mh, kCutI);
  475.     DisableItem(mh, kCopyI);
  476.     DisableItem(mh, kPasteI);
  477.     DisableItem(mh, kClearI);
  478.     mh = GetMHandle(kRandomDotMenu);
  479.     DisableItem(mh, kGrayI);
  480.     DisableItem(mh, kBWStereoI);
  481.     DisableItem(mh, kGrayStereoI);
  482.     SetRandomDotMenu(0);
  483. }
  484.  
  485. /* RandomDotActivateMenus - 
  486.  */
  487. static void RandomDotActivateMenus(void){
  488.     MenuHandle    mh;
  489.     Rect        r;
  490.  
  491.     mh = GetMHandle(kFileMenu);
  492.     EnableItem(mh, kCloseI);
  493.     EnableItem(mh, kSaveI);
  494.     EnableItem(mh, kSaveAsI);
  495.     EnableItem(mh, kPrintI);
  496.     mh = GetMHandle(kEditMenu);
  497.     EnableItem(mh, kCutI);
  498.     EnableItem(mh, kCopyI);
  499.     EnableItem(mh, kPasteI);
  500.     EnableItem(mh, kClearI);
  501.     mh = GetMHandle(kRandomDotMenu);
  502.     EnableItem(mh, kGrayI);
  503.     EnableItem(mh, kBWStereoI);
  504.     r = (**LMGetGrayRgn()).rgnBBox;
  505.     if(world.hasColorQD && (**(**GetMaxDevice(&r)).gdPMap).pixelSize > 1){
  506.         EnableItem(mh, kGrayStereoI);
  507.         EnableItem(mh, kShimmerI);
  508.     }
  509. }
  510.  
  511. /* RandomDotSetRandomDotMenu - from flag to menu.
  512.  */
  513. static void RandomDotSetRandomDotMenu(void){
  514.     RandomDotWindowPtr    win;
  515.  
  516.     win = (RandomDotWindowPtr) qd.thePort;
  517.     switch(win->flags & kShow){
  518.     case bShowGray:            SetRandomDotMenu(kGrayI);        break;
  519.     case bShowBWStereo:        SetRandomDotMenu(kBWStereoI);    break;
  520.     case bShowGrayStereo:    SetRandomDotMenu(kGrayStereoI);    break;
  521.     case bShowGrayStereo|bIsShimmer:    SetRandomDotMenu(kShimmerI);    break;
  522.     }
  523. }
  524.  
  525. /* RandomDotActivate - on activate
  526.  */
  527. void RandomDotActivate(void){
  528.     RandomDotWindowPtr    win;
  529.  
  530.     win = (RandomDotWindowPtr) qd.thePort;
  531.     ShowControl(win->hScroll);
  532.     ShowControl(win->vScroll);
  533.     DrawGrowIcon(qd.thePort);
  534.     RandomDotActivateMenus();
  535.     RandomDotSetRandomDotMenu();
  536. }
  537.  
  538. /* RandomDotDeactivate - on deactivate
  539.  */
  540. void RandomDotDeactivate(void){
  541.     Rect    r;
  542.     RandomDotWindowPtr    win;
  543.  
  544.     win = (RandomDotWindowPtr) qd.thePort;
  545.     r = qd.thePort->portRect;
  546.     r.top = r.bottom - (kScrollBarWidth-1);
  547.     r.left = r.right - (kScrollBarWidth-1);
  548.     EraseRect(&r);
  549.     HideControl(win->hScroll);
  550.     HideControl(win->vScroll);
  551. }
  552.  
  553. /* RandomDotGrow - call this after a grow
  554.     constrains the grow size, 
  555.     moves the scroll bars.
  556.     sets the new maximums.
  557.  */
  558. void RandomDotGrow(void){
  559.     RandomDotWindowPtr    win;
  560.     Point                size, maxSize, newSize;
  561.     Rect                r;
  562.  
  563.  
  564.     /* constrains the grow size, 
  565.      */
  566.     win = (RandomDotWindowPtr) qd.thePort;
  567.     size.h = qd.thePort->portRect.right - qd.thePort->portRect.left;
  568.     size.v = qd.thePort->portRect.bottom - qd.thePort->portRect.top;
  569.     maxSize.h = kScrollBarWidth + win->frame.right - win->frame.left;
  570.     maxSize.v = kScrollBarWidth + win->frame.bottom - win->frame.top;
  571.     newSize.h = Min(size.h, maxSize.h);
  572.     newSize.v = Min(size.v, maxSize.v);
  573.     if(size.h != newSize.h || size.v != newSize.v){
  574.         SizeWindow(qd.thePort, newSize.h, newSize.v, FALSE);
  575.     }
  576.  
  577.     /* moves the scroll bars.
  578.      */
  579.     r = qd.thePort->portRect;
  580.     MoveControl(win->vScroll, r.right-kScrollBarWidth, -1 + r.top);
  581.     SizeControl(win->vScroll, kScrollBarWidth+1, 2 + r.bottom - (r.top + kScrollBarWidth));
  582.     MoveControl(win->hScroll, -1, r.bottom - kScrollBarWidth);
  583.     SizeControl(win->hScroll, 2 + r.right - kScrollBarWidth, kScrollBarWidth+1);
  584.  
  585.     /* sets the new maximums.
  586.      */
  587.     SetControlMaximum(win->hScroll, Max(0, maxSize.h - newSize.h));
  588.     SetControlMaximum(win->vScroll, Max(0, maxSize.v - newSize.v));
  589. }
  590.  
  591. /* RandomDotGrowBounds - tell the growBounds how big a rect to use.
  592.  */
  593. void RandomDotGrowBounds(Rect *rp){
  594.     RandomDotWindowPtr    win;
  595.  
  596.     win = (RandomDotWindowPtr) qd.thePort;
  597.     rp->left = kScrollBarWidth*4;
  598.     rp->top = kScrollBarWidth*4;
  599.     rp->right = Min( kScrollBarWidth + win->frame.right - win->frame.left,
  600.         (**LMGetGrayRgn()).rgnBBox.right - (**LMGetGrayRgn()).rgnBBox.left);
  601.     rp->bottom = Min( kScrollBarWidth + win->frame.bottom - win->frame.top,
  602.         (**LMGetGrayRgn()).rgnBBox.bottom - (**LMGetGrayRgn()).rgnBBox.top);
  603. }
  604.  
  605. /* RandomDotIdealSize - called by ZoomTheWindow to tell it how big a rect to use.
  606.     this is almost what RandomDotGrowBounds, we just need to remove the minimum info
  607.     and replace it by zeroes.
  608.  */
  609. void RandomDotIdealSize(WindowPtr win, Rect *rp){
  610.     WindowPtr    savePort;
  611.  
  612.     GetPort(&savePort);
  613.     SetPort(win);
  614.     RandomDotGrowBounds(rp);
  615.     rp->left = rp->top = 0;
  616.     SetPort(savePort);
  617. }
  618.  
  619.  
  620.  
  621.